/*
	game.h		Game States
	Copyright (c) 2004, 2005, 2006 Kriang Lerdsuwanakij
	email:		lerdsuwa@users.sourceforge.net

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef GAME_H
#define GAME_H

#include <pthread.h>


#include <sys/types.h>
#include <time.h>

#include <exception>
#include <stdexcept>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <string>
#include <deque>
#include <vector>

#include "gameinfo.h"

/*************************************************************************
	AI variables
*************************************************************************/

extern pthread_t	ai_thread;
extern pthread_attr_t	ai_thread_attr;
extern bool		ai_running;			// Lock required for access
extern bool		ai_tampered;

extern pthread_mutex_t	input_lock;
extern volatile int	input_pos;			// Lock required for access

/*************************************************************************
	Game states
*************************************************************************/

void new_game(game_info &g);
void new_game(game_info &g, const byte_board_info &b, int color = BLACK);

extern game_info cur_game_info;

extern std::deque<int>	move_queue;

extern int		time_player;	// Time spent in a move
extern int		clock_player;	// Remaining clock for a player
extern int		time_player_animate_delay;

/*************************************************************************
	Configurations - Not front-end specific
*************************************************************************/

const int NUM_GAME_MODE = 6;
enum game_mode_type {
	COMPUTER_NONE,
	COMPUTER_BLACK,
	COMPUTER_WHITE,
	COMPUTER_BOTH,
	COMPUTER_ALTERNATE,
	COMPUTER_RANDOM
};
extern const char *game_mode_name[NUM_GAME_MODE];

struct level_info_type {
	int midgame_depth;
	int num_empty_winlossdraw;
	int num_empty_exact;
};

const int NUM_LEVEL_INFO = 5;
extern level_info_type level_info[NUM_LEVEL_INFO];

const int LEVEL_CUSTOM = NUM_LEVEL_INFO;
const int LEVEL_CUSTOM_FILE = 99;
extern int computer_level;

extern level_info_type current_level_info;

extern const char *level_name[NUM_LEVEL_INFO+1];

const int NUM_OPENING_VAR = 6;
extern int opening_var;
extern const char *opening_var_name[NUM_OPENING_VAR];

extern bool log_opening;	// Not user configurable yet
extern bool log_move;
extern bool animate_opening;
extern bool redo_ai_move;

const int NUM_ANIMATE_DELAY = 5;
extern int animate_delay;

extern std::string opening_name;
extern int opening_player;
extern std::deque<int> opening_move_queue;

const int NUM_START_GAME_MODE = 2;
enum start_game_mode_type {
	START_GAME_INITIAL,
	START_GAME_RANDOM
};
extern const char *start_game_mode_name[NUM_START_GAME_MODE];
extern start_game_mode_type start_game_mode;
extern int start_random_game_pieces;

extern bool show_toolbar;
extern bool show_pattern_evaluation;
extern bool show_game_history;

extern bool show_border;
extern bool hint_move;
extern bool show_last_move;
extern std::string theme_name;

extern byte_board_info *view_board_ptr;
enum view_mode_type {
	VIEW_MODE_NONE,
	VIEW_MODE_HISTORY,
	VIEW_MODE_EDIT
};
extern view_mode_type view_mode;
extern int view_position;
extern int view_player;
void set_view_mode(view_mode_type);

/*************************************************************************
	Other functions that have to be provided by front ends
*************************************************************************/

void load_pixmaps(bool);
void resize_board_widget();
void draw_board();
void computer_move();
void human_move();
void cancel_input();
void new_game();

/*************************************************************************
	Game mode functions
*************************************************************************/

game_mode_type get_game_mode();
void set_game_mode(game_mode_type game_mode_);
const char *get_game_mode_string();
bool is_computer_player(int color);
void switch_computer_game_mode();
bool get_wait_player();
void maybe_set_ai_tampered();
int get_computer_move(double komi = 0.0);
int get_computer_winlossdraw_move(double komi = 0.0);
int get_computer_exact_move();

/*************************************************************************
	Home directory functions
*************************************************************************/

const std::string &get_user_home_dir();

/*************************************************************************
	Logging function
*************************************************************************/

void log_history(const std::string &filename,
		 const std::string &black_name,
		 const std::string &white_name);

/*************************************************************************
	State update
*************************************************************************/

				// Useful hint to manage move lists
enum update_state_type {
	UPDATE_ALL,		// Game changed
	UPDATE_BACKWARD,	// Moves removed
	UPDATE_FORWARD,		// Moves added
	UPDATE_NONE		// No moves, repaint board/status
};
typedef void (*update_func)(update_state_type, void *);

struct update_item {
	update_func	func;
	void 		*data;
	update_item(update_func f, void *d) : func(f), data(d) {}
};

class update_hook {
		std::vector<update_item> vec;
	public:
		void update(update_state_type);
		void update_except(update_state_type u, update_func f, void *d);
		void add(update_func f, void *d);
		void remove(update_func f, void *d);
};

extern update_hook update_move;
extern update_hook update_game_list;

/*************************************************************************
	Utility functions
*************************************************************************/

const char *find_opening_name(byte_board_info *);
const char *find_opening_name();

#endif /* GAME_H */
